package com.ld.shieldsb.common.composition.util;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.BigDecimalConverter;
import org.apache.commons.beanutils.converters.DoubleConverter;
import org.apache.commons.beanutils.converters.IntegerConverter;
import org.apache.commons.beanutils.converters.LongConverter;
import org.apache.commons.beanutils.converters.ShortConverter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ld.shieldsb.common.core.collections.MapUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 聚合工具类：：转换工具类，包括map与model的互相转换，model与json字符串的互相转换等与类转换相关的操作
 * 
 * @ClassName ConvertUtil
 * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
 * @date 2018年11月16日 上午9:30:40
 *
 */
@Slf4j
public class ConvertUtil {
    static {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true); // #打开AutoType， 在fastjson1.2.25之后的版本，以及所有的.sec01后缀版本中，autotype功能是受限的
        // beanUtil工具类转换时null不转换为0
        ConvertUtils.register(new LongConverter(null), Long.class);
        ConvertUtils.register(new ShortConverter(null), Short.class);
        ConvertUtils.register(new IntegerConverter(null), Integer.class);
        ConvertUtils.register(new DoubleConverter(null), Double.class);
        ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class);

    }

    private ConvertUtil() {
        // 工具类无需对象实例化
    }

    // 将MapUtils工具类聚合进来
    public static class MapUtil extends MapUtils {
    }

    /**
     * map转对象
     * 
     * @Title map2obj
     * @author 吕凯
     * @date 2018年11月16日 上午10:10:14
     * @param clazz
     * @param map
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     *             T
     */
    public static <T, V> T map2obj(Map<String, V> map, Class<T> clazz)
            throws InstantiationException, IllegalAccessException, InvocationTargetException {
        return map2obj(map, clazz, false);
    }

    /**
     * 将Map转对象
     * 
     * @param clazz
     *            目标对象的类
     * @param map
     *            待转换Map
     * @param toCamelCase
     *            是否去掉下划线
     */
    public static <T, V> T map2obj(Map<String, V> map, Class<T> clazz, boolean toCamelCase)
            throws InstantiationException, IllegalAccessException, InvocationTargetException {
        return MapUtils.toObject(clazz, map, toCamelCase);
    }

    /**
     * 对象转Map
     * 
     * @param object
     *            目标对象
     * @return 转换出来的值都是String
     */
    public static Map<String, String> obj2Map(Object object)
            throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        return MapUtils.toMap(object);
    }

    /**
     * 对象转Map
     * 
     * @param object
     *            目标对象
     * @return 转换出来的值类型是原类型
     */
    public static Map<String, Object> obj2OrigMap(Object object)
            throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        return MapUtils.toNavMap(object);
    }

    /**
     * 对象转json字符串
     * 
     * @param object
     *            目标对象
     * @return 转换出来的值类型是原类型
     */
    public static String obj2JsonStr(Object object) {
        try {
            return JSON.toJSONString(object);
        } catch (Exception e) {
            log.error("", e);
        }
        return null;
    }

    /**
     * 
     * 对象转json字符串（web用，不带类信息，转为浏览器格式化）
     * 
     * @Title obj2JsonStr4Web
     * @author 吕凯
     * @date 2018年11月16日 下午12:43:26
     * @param object
     *            带转换对象
     * @param WriteMapNullValue
     *            空对象是否写入
     * @return String
     */
    public static String obj2JsonStr4Web(Object object) {
        return obj2JsonStr4Web(object, false);
    }

    /**
     * 
     * 对象转json字符串（web用，不带类信息，转为浏览器格式化）
     * 
     * @Title obj2JsonStr4Web
     * @author 吕凯
     * @date 2019年2月28日 下午5:46:40
     * @param object
     *            待转换对象
     * @param writeMapNullValue
     *            空对象是否写入
     * @return String json字符串
     */
    public static String obj2JsonStr4Web(Object object, boolean writeMapNullValue) {
        List<SerializerFeature> features = new ArrayList<>();
        features.add(SerializerFeature.BrowserCompatible);
        if (writeMapNullValue) {
            features.add(SerializerFeature.WriteMapNullValue);
        }
        return JSON.toJSONString(object, features.toArray(new SerializerFeature[0]));
    }

    /**
     * json字符串转对象，当json中带有class信息时，可直接调用该方法
     * 
     * @Title jsonString2Obj
     * @author 吕凯
     * @date 2018年11月16日 上午11:37:09
     * @param text
     * @return Object
     */
    public static Object jsonStr2Obj(String text) {
        try {
            return JSON.parse(text);
        } catch (Exception e) {
            log.error("", e);
        }
        return null;
    }

    /**
     * 
     * json字符串转指定对象，，当json中不含有class信息时，或者希望转为其他类时调用该方法
     * 
     * @Title jsonString2Obj
     * @author 吕凯
     * @date 2018年11月16日 上午11:38:07
     * @param text
     * @param clazz
     * @return T
     */
    public static <T> T jsonStr2Obj(String text, Class<T> clazz) {
        try {
            return JSON.parseObject(text, clazz);
        } catch (Exception e) {
            log.error("", e);
        }
        return null;
    }

}
